package com.mypj.base.common.utils;

import com.mypj.base.entity.dto.HttpInfo;
import com.mypj.base.entity.dto.MyCookie;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.cookie.Cookie;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.util.*;

@Slf4j
public class HttpClientUtil {
    /*========================GET==============================*/

    public static HttpInfo getForString(String url, Map<String, String> header, Cookie[] cookies, HttpHost httpHost, String charset) {
        BasicCookieStore cookieStore = new BasicCookieStore();
        if (cookies != null && cookies.length > 0) {
            cookieStore.addCookies(cookies);
        }
        CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultCookieStore(cookieStore)//设置Cookie
                .build();
        CloseableHttpResponse response = null;
        HttpGet get = new HttpGet(url);
        if (httpHost != null) {
            get.setConfig(RequestConfig.custom().setProxy(httpHost).build());
        }
        try {
            //设置请求头
            if (header != null && !header.isEmpty()) {
                for (Map.Entry<String, String> current : header.entrySet()) {
                    get.addHeader(current.getKey(), current.getValue());
                }
            }
            response = httpClient.execute(get);
            return resultCheck(response, charset);
        } catch (Exception e) {
            e.printStackTrace();
            return new HttpInfo(-1, "请求错误:" + e, null);
        } finally {
            close(httpClient, response);
        }
    }

    public static HttpInfo getWithHttpClient(CloseableHttpClient httpClient, String url, Map<String, String> header, String charset) {
        CloseableHttpResponse response = null;
        try {
            HttpGet get = new HttpGet(url);
            //设置请求头
            if (header != null && !header.isEmpty()) {
                for (Map.Entry<String, String> current : header.entrySet()) {
                    get.addHeader(current.getKey(), current.getValue());
                }
            }
            response = httpClient.execute(get);
            return resultCheck(response, charset);
        } catch (Exception e) {
            e.printStackTrace();
            return new HttpInfo(-1, "请求错误:" + e);
        } finally {
            close(null, response);
        }
    }

    /*========================POST==============================*/

    public static HttpInfo postForString(String url, Map<String, String> header, Map<String, String> params, Cookie[] cookies, HttpHost httpHost, String charset) {
        BasicCookieStore cookieStore = new BasicCookieStore();
        if (cookies != null && cookies.length > 0) {
            cookieStore.addCookies(cookies);
        }
        CloseableHttpClient httpClient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();
        CloseableHttpResponse response = null;
        HttpPost post = new HttpPost(url);
        if (httpHost != null) {
            post.setConfig(RequestConfig.custom().setProxy(httpHost).build());
        }
        try {
            //设置请求头
            if (header != null && !header.isEmpty()) {
                for (Map.Entry<String, String> current : header.entrySet()) {
                    post.addHeader(current.getKey(), current.getValue());
                }
            }
            //设置请求参数
            List<NameValuePair> list = new ArrayList<>();
            if (params != null && !params.isEmpty()) {
                for (Map.Entry<String, String> current : params.entrySet()) {
                    list.add(new BasicNameValuePair(current.getKey(), current.getValue()));
                }
            }
            if (list.size() > 0) {
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, charset);
                post.setEntity(entity);
            }
            //发起请求
            response = httpClient.execute(post);
            return resultCheck(response, charset);
        } catch (Exception e) {
            e.printStackTrace();
            return new HttpInfo(-1, "请求错误:" + e, null);
        } finally {
            close(httpClient, response);
        }
    }

    public static HttpInfo postWithHttpClient(CloseableHttpClient httpClient, String url, Map<String, String> header, Map<String, String> params, String charset) {
        CloseableHttpResponse response = null;
        try {
            HttpPost post = new HttpPost(url);
            //设置请求头
            if (header != null && !header.isEmpty()) {
                for (Map.Entry<String, String> current : header.entrySet()) {
                    post.addHeader(current.getKey(), current.getValue());
                }
            }
            //设置请求参数
            List<NameValuePair> list = new ArrayList<>();
            if (params != null && !params.isEmpty()) {
                for (Map.Entry<String, String> current : params.entrySet()) {
                    list.add(new BasicNameValuePair(current.getKey(), current.getValue()));
                }
            }
            if (list.size() > 0) {
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, charset);
                post.setEntity(entity);
            }
            response = httpClient.execute(post);
            return resultCheck(response, charset);
        } catch (Exception e) {
            return new HttpInfo(-1, "请求错误:" + e);
        } finally {
            close(null, response);
        }
    }

    public static HttpInfo postWithHttpClientAndJsonBody(CloseableHttpClient httpClient, String url, Map<String, String> header, String body, String charset) {
        CloseableHttpResponse response = null;
        try {
            HttpPost post = new HttpPost(url);
            //设置请求头
            if (header != null && !header.isEmpty()) {
                for (Map.Entry<String, String> current : header.entrySet()) {
                    post.addHeader(current.getKey(), current.getValue());
                }
            }
            //设置请求参数
            post.setEntity(new StringEntity(body));
            response = httpClient.execute(post);
            return resultCheck(response, charset);
        } catch (Exception e) {
            return new HttpInfo(-1, "请求错误:" + e);
        } finally {
            close(null, response);
        }
    }

    public static HttpInfo postForStringWithJsonBody(String url, Map<String, String> header, String body, Cookie[] cookies, HttpHost httpHost, String charset) {
        BasicCookieStore cookieStore = new BasicCookieStore();
        if (cookies != null && cookies.length > 0) {
            cookieStore.addCookies(cookies);
        }
        CloseableHttpClient httpClient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();
        CloseableHttpResponse response = null;
        HttpPost post = new HttpPost(url);
        if (httpHost != null) {
            post.setConfig(RequestConfig.custom().setProxy(httpHost).build());
        }
        try {
            //设置请求头
            if (header != null && !header.isEmpty()) {
                for (Map.Entry<String, String> current : header.entrySet()) {
                    post.addHeader(current.getKey(), current.getValue());
                }
            }
            //设置请求参数(jsonBody)
            post.setEntity(new StringEntity(body));
            //发起请求
            response = httpClient.execute(post);
            return resultCheck(response, charset);
        } catch (Exception e) {
            e.printStackTrace();
            return new HttpInfo(-1, "请求错误:" + e, null);
        } finally {
            close(httpClient, response);
        }
    }

    //检查响应结果并且返回
    private static HttpInfo resultCheck(CloseableHttpResponse response, String charset) throws Exception {
        if (response != null) {
            int responseCode = response.getStatusLine().getStatusCode();
            if (responseCode == 200) {
                return new HttpInfo(responseCode, "请求成功，响应码:" + responseCode, EntityUtils.toString(response.getEntity(), charset));
            } else if (responseCode == 302) {
                return new HttpInfo(responseCode, "需要重定向，响应码:" + responseCode, response.getFirstHeader("location").getValue());
            } else if (responseCode == 400 || responseCode == 401) {
                return new HttpInfo(responseCode, "认证失败，请检查账号密码");
            } else {
                return new HttpInfo(responseCode, "网络错误，响应码:" + responseCode);
            }
        } else {
            return new HttpInfo(-1, "请求返回为null");
        }
    }

    //关闭连接
    public static void close(CloseableHttpClient httpClient, CloseableHttpResponse response) {
        try {
            if (httpClient != null)
                httpClient.close();
            if (response != null)
                response.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Cookie[] cookieMapToArray(Map<String, Cookie> cookieMap) {

        if (cookieMap == null || cookieMap.size() <= 0) {
            return null;
        }
        Set<String> keys = cookieMap.keySet();
        Cookie[] cookies = new Cookie[cookieMap.size()];
        int n = 0;
        for (String key : keys) {
            cookies[n++] = cookieMap.get(key);
        }
        return cookies;
    }

    public static Cookie[] cookieListToArray(List<Cookie> cookieList) {
        if (cookieList == null || cookieList.size() <= 0) {
            return null;
        }
        Cookie[] cookies = new Cookie[cookieList.size()];
        int n = 0;
        for (Cookie cookie : cookieList) {
            cookies[n++] = cookie;
        }
        return cookies;
    }

    public static Map<String, Cookie> cookieArrayToMap(Cookie[] cookieArray) {
        if (cookieArray == null || cookieArray.length <= 0) {
            return null;
        }
        Map<String, Cookie> cookieMap = new HashMap<>();
        for (Cookie cookie : cookieArray) {
            cookieMap.put(cookie.getName(), cookie);
        }
        return cookieMap;
    }

    public static List<MyCookie> httpCookieToMyCookie(List<Cookie> cookieList) {
        List<MyCookie> myCookieList = new ArrayList<>();
        if (cookieList != null && cookieList.size() > 0) {
            for (Cookie cookie : cookieList) {
                MyCookie myCookie = new MyCookie();
                myCookie.setName(cookie.getName());
                myCookie.setValue(cookie.getValue());
                myCookie.setCookieDomain(cookie.getDomain());
                myCookie.setCookieExpiryDate(cookie.getExpiryDate());
                myCookie.setCookiePath(cookie.getPath());
                myCookieList.add(myCookie);
            }
        }
        return myCookieList;
    }

    public static List<Cookie> MyCookieToHttpCookie(List<MyCookie> myCookieList) {
        List<Cookie> cookieList = new ArrayList<>();
        if (myCookieList != null && myCookieList.size() > 0) {
            for (MyCookie myCookie : myCookieList) {
                BasicClientCookie cookie = new BasicClientCookie(myCookie.getName(), myCookie.getValue());
                cookie.setDomain(myCookie.getCookieDomain());
                cookie.setExpiryDate(myCookie.getCookieExpiryDate());
                cookie.setPath(myCookie.getCookiePath());
                cookieList.add(cookie);
            }
        }
        return cookieList;
    }
}
